#ifndef _Node_H_
#define _Node_H_

/******************************************************************************

Description:
  Node class, stores a node in the tree. Intended for using in fp-trees.

Author: Tayfun Sen
Website: http://blog.tayfunsen.com
 
 *****************************************************************************/

// Standard libraries.
#include <iostream>
#include <ext/hash_map>
// Boost libraries for serializing.
#include <boost/tokenizer.hpp>
#include <boost/archive/tmpdir.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/export.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/hash_map.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/string.hpp>
#include <boost/mpi.hpp>
// Custom libraries.
// shared.hpp has fix so that hash_map accepts strings as well.
#include "shared.hpp"
#include "Globals.hpp"

using namespace std;
using namespace __gnu_cxx;


class Node {
    public:
        // Create a node using item and its count.
        Node(string itemArg = "root", int countArg = 1, int lengthArg = 0)
            : item(itemArg), count(countArg), length(lengthArg) {
            next = parent = NULL;
        }

        // Copy constructor is used when returning by value, passing by value
        // etc. Is it really needed? I don't think so.

        ~Node() {
        }

        // Basically accessors for getting the private data back.
        string getItem() const {
            return item;
        }

        int getCount() const {
            return count;
        }

        void setCount(int countArg) { count = countArg; }

        void setMaxCount(int countArg) { 
            if (countArg > count) 
                count  = countArg; 
        }

        void incCount(int more = 1) {
            count += more;
        }

        // Sets the next node this node is pointing to. The next node will
        // be a node with the same item, so one can traverse while mining in
        // the CLOSET+ algorithm.
        void setNext(Node * node) {
            next = node;
        }

        Node * getNext() {
            return next;
        }

        const hash_map<string, Node *> & getChildren() const {
            return children;
        }

        hash_map<string, Node *> & getVarChildren() {
            return children;
        }

        // Get the node from children with the given item name.
        Node * getNode(string item) {
            hash_map<string, Node *>::iterator it = children.find(item);
            if (it != children.end())
                return (*it).second;
            else 
                return NULL;
        }

        int insertChild(Node * child) {
            // If the child exists do not insert it.
            if (children.find(child->item) != children.end()) {
                cerr << "Error in Node::insertChild.\n Node to be inserted" <<
                    " is already a child." << endl;
                return -1;
            }

            child->setParent(this);
            children[child->item] = child;
            return 0;
        }

        Node * getParent() {
            return parent; }

        int getLength() const { return length; }

        // This is the only method implemented in the .cpp file. This method 
        // is for debugging purposes. All the other methods are implemented in
        // this header file.
        void print(Node *);

    private:
        friend class boost::serialization::access;
        template<class Archive>
            void serialize(Archive & ar, const unsigned int version) {
                ar & item;
                ar & count;
                ar & length;
                ar & children;
                ar & next;
                ar & parent;
            }
        //*****************************************
        //************ data ***********************
        //*****************************************
        string item;
        int count;
        // For result tree we need length as well.
        int length;
        // To enable easy navigation to children wrt item.
        hash_map<string, Node *> children;
        // Have pointers to next and parent elements.
        Node * next, * parent;
        //*****************************************
        //************ methods ********************
        //*****************************************
        void setParent(Node * parentArg) {
            parent = parentArg;
        }
};

#endif

